#include <algorithm>
#include <map>
using namespace std;

#include "hladata_parser.h"
#include "hla_processor.h"

class ProcessorsRegistry
{
public:
    struct HlaProcComp
    {
        bool operator() (const HlaProcessor* p1, const HlaProcessor* p2) const
        {
            return p1->get_priority() < p2->get_priority();
        }
    };

    typedef set<HlaProcessor*, HlaProcComp>::const_iterator Iterator;

    static void destroy();
    static void register_processor(HlaProcessor*);
    static Iterator begin();
    static Iterator end();

private:
    set<HlaProcessor*, HlaProcComp> _processors;
    static ProcessorsRegistry* _registry;

    static ProcessorsRegistry* _this()
    {
        if (_registry == NULL)
            _registry = new ProcessorsRegistry;

        return _registry;
    }

    ~ProcessorsRegistry();
};

ProcessorsRegistry* ProcessorsRegistry::_registry = NULL;

static bool process(const char* file);

int main(int argc, char* argv[])
{
    int ret = EXIT_FAILURE;

    if (argc != 2)
        cerr << "Usage: " << argv[0] << " name.xml > output.xml" << endl;
    else
    {
        //results.set_verbose(true);
        if (process(argv[1]))
            ret = EXIT_SUCCESS;
    }

    return ret;
}

static bool process(const char* file)
{
    bool ret;
    HlaData data;

    ret = parseHlaData(file, data);

    if (ret)
    {
        Spreadsheet spreadsheet;

        ProcessorsRegistry::Iterator proc;

        for (proc = ProcessorsRegistry::begin(); proc != ProcessorsRegistry::end(); ++proc)
            (*proc)->process(data);

        for (proc = ProcessorsRegistry::begin(); proc != ProcessorsRegistry::end(); ++proc)
            (*proc)->generate_results(spreadsheet);

        ProcessorsRegistry::destroy();
        //results.generate_sheets(spreadsheet);
        //dispersion_results.generate_sheets(spreadsheet);
    }

    return ret;
}


void register_processor(HlaProcessor* processor)
{
    ProcessorsRegistry::register_processor(processor);
}

ProcessorsRegistry::~ProcessorsRegistry()
{
    delete_container(_processors);
}       

void ProcessorsRegistry::destroy()
{
    delete _registry;
    _registry = NULL;
}

void ProcessorsRegistry::register_processor(HlaProcessor* processor)
{
    insert_into(_this()->_processors, processor);
}

ProcessorsRegistry::Iterator ProcessorsRegistry::begin()
{
    return _this()->_processors.begin();
}

ProcessorsRegistry::Iterator ProcessorsRegistry::end()
{
    return _this()->_processors.end();
}

